﻿using System;
using System.Collections.Generic;
using Shell.DomainDot;
using Shell.PocoDot;
using Shell.PocoDot.Configurations;
using System.Linq;

namespace DataProvider
{

    class CompanyContext
    {
        public void SetCompanies(Func<IQueryable<Company>> c)
        { 
            c.Invoke()
        }
        
    }







    class Program
    {
        static void Main(string[] args)
        {
            ObjectSeeker.Seeker = new MockContainer();

            var provider = new ProviderConfiguration("conn");
            provider.CreateIfNotExists = true;

            provider.Register<City>();
            provider.Register<Company>();
            provider.Register<Category>();
            provider.Register<Contract>();
            provider.Register<Company, Contract>(Relationships.WithMany, Relationships.WithOne);
            provider.Register<Company, Category>(Relationships.WithOne, Relationships.WithMany);
            provider.Register<Company, City>(Relationships.WithOne, Relationships.WithMany);

            var factory = DomainDotFactory.Factory;
            var registerer = factory.Create<CompanyRegisterer>();
            var contractId = registerer.Register(new Company
               {
                   Name2 = "Huawei"
               },
               new Contract
               {
                   Name = "5he11",
                   Tel = "13011111111"
               },
               Guid.Parse("afa3386b-26ed-4099-b68e-43ea9dcee22e"),
               Guid.Parse("afa3386b-26ed-4099-b68e-43ea9dcee22f"));

            var contractManager = factory.Create<ContractManager>(contractId);
            var comp = contractManager.GetCompany();
            Console.Write(comp.Name2);
        }
    }

    public class CompanyRegisterer : DomainDotBase
    {
        public WithAll<CompanyContext, Company> Companies { private get; set; }

        public Guid Register(Company company, Contract contract, Guid cityId, Guid categoryId)
        {
            var instnace = this.Companies.Create(company);
            foreach (var item in this.Companies.Instances)
            {
                Console.WriteLine(item.Instance.Name2);
            }
            this.Companies.Submit();
            instnace.BindCategory(categoryId);
            instnace.BindCity(cityId);
            var c = instnace.AddContract(contract);
            return c.Id;
        }
    }

    class ContractManager : DomainDotBase<Contract>
    {
        public WithOne<Company> Company { private get; set; }

        public Company GetCompany()
        {
            return this.Company.Instance;
        }
    }

    public class CompanyContext : DomainDotBase<Company>
    {
        public WithMany<Contract> ContractsContains { private get; set; }

        public WithMany<Contract> ContractsContains2 { private get; set; }

        public WithOne<City> CityBelonged { private get; set; }

        public WithOne<Category> CategoryBelonged { private get; set; }

        public Contract AddContract(Contract contract)
        {
            var created = NewMethod(contract);
            created = NewMethod(contract);
            created = NewMethod(contract);
            created = NewMethod(contract);
            created = NewMethod(contract);
            created = NewMethod(contract);
            created = NewMethod(contract);
            created = NewMethod(contract);

            foreach (var item in this.ContractsContains2.Instances)
            {
                Console.WriteLine(item.Name);
            }

            return created;
        }

        private Contract NewMethod(Contract contract)
        {
            var created = this.ContractsContains.Create();
            created.Name = contract.Name + "1";
            created.Tel = contract.Tel;
            this.ContractsContains.Submit();
            return created;
        }

        public void BindCity(Guid cityId)
        {
            this.CityBelonged.Bind(cityId);
            this.CityBelonged.Submit();
        }

        public void BindCategory(Guid categoryId)
        {
            this.CategoryBelonged.Bind(categoryId);
            this.CategoryBelonged.Submit();
        }
    }

    public class City : PocoDotBase
    {
        public string Name { get; set; }
    }

    public class Company : PocoDotBase
    {
        public string Name2 { get; set; }
    }

    public class Category : PocoDotBase
    {
        public string Name { get; set; }
    }

    public class Contract : PocoDotBase
    {
        public string Name { get; set; }

        public string Tel { get; set; }
    }

    class MockContainer : IObjectSeeker
    {
        public T Seek<T>() where T : class
        {
            if (typeof(T).IsAssignableFrom(typeof(IRepositoryFactory)))
            {
                return new EfRepositoryFactory() as T;
            }
            if (typeof(T).IsAssignableFrom(typeof(IDataContextFactory)))
            {
                return new EfDataContextFactory() as T;
            }
            return Activator.CreateInstance(typeof(T)) as T;
        }

        public IEnumerable<T> SeekAll<T>() where T : class
        {
            return null;
        }

        public void Dispose()
        {
        }
    }
}
